package com.substanceofcode.data.midp;

import com.substanceofcode.data.FileIOException;
import com.substanceofcode.data.midp.RsfsFileTest.DummyFile;

import net.sf.microlog.core.Logger;
import net.sf.microlog.core.LoggerFactory;

import junitj2me.framework.TestCase;

public class RsfsSplitFileTest extends TestCase
{
    private final static Logger LOG = LoggerFactory.getLogger();

    protected void setUp() throws Exception
    {
        FileSystemImpl.resetStaticData();
        FileSystemImpl.getFileSystem().formatFileSystem();
    }

    private static final String TEST_FILENAME = "file:////somedirectory/another/bigtestfile";

    public void test1()
    {
        LOG.info( "testSaveManySmallFilesDefaultSettings" );

        try
        {
            FileSystemImpl fileSystemImpl = FileSystemImpl.getFileSystem();

            assertEquals( "iCurrentRecordStoreNumber 1", 1, fileSystemImpl.iCurrentRecordStoreNumber );
            //assertEquals( "iRecordsInCurrentRecordStore 0", 0, fileSystem.iRecordsInCurrentRecordStore );

            DummyFile dummyFile = new DummyFile( "A".getBytes(), "text" );

            for( int i = 1; i <= 10; ++i )
            {
                FileSystemImpl.getFileSystem().saveFile( TEST_FILENAME + i, dummyFile, true );

                // We shouldn't need to move to a new record store for this few files of this size.
                assertEquals( "iCurrentRecordStoreNumber 1", 1, fileSystemImpl.iCurrentRecordStoreNumber );

                // We should be adding a new record each time.
                //assertEquals( "iRecordsInCurrentRecordStore " + i, i, fileSystem.iRecordsInCurrentRecordStore );

                RsfsFileTest.assertFileContentsEqual( TEST_FILENAME + i, "A".getBytes() );

                FileSystemImpl.getFileSystem().deleteFile( TEST_FILENAME + i );

                assertFalse( fileSystemImpl.exists( TEST_FILENAME + i ) );
            }

        }
        catch( Exception e )
        {
            fail( e.getMessage() );
        }
    }

    public void test2()
    {
        LOG.info( "testSaveManySmallFilesSingleRecordPerRecordStoreAllowed" );

        try
        {
            FileSystemImpl fileSystemImpl = FileSystemImpl.getFileSystem();
            fileSystemImpl.setMaxRecordsPerRecordStore( 1 );

            assertEquals( "iCurrentRecordStoreNumber 1", 1, fileSystemImpl.iCurrentRecordStoreNumber );
            //assertEquals( "iRecordsInCurrentRecordStore 0", 0, fileSystem.iRecordsInCurrentRecordStore );

            DummyFile dummyFile = new DummyFile( "A".getBytes(), "text" );

            for( int i = 1; i <= FileSystemImpl.DEFAULT_RMS_NUMBER_RECORD_STORES; ++i )
            {
                FileSystemImpl.getFileSystem().saveFile( TEST_FILENAME + i, dummyFile, true );

                // We shouldn't need to move to a new record store for this few files of this size.
                assertEquals( "iCurrentRecordStoreNumber " + i, i, fileSystemImpl.iCurrentRecordStoreNumber );

                // We should be adding a new record each time.
                //assertEquals( "iRecordsInCurrentRecordStore 1", 1, fileSystem.iRecordsInCurrentRecordStore );

                RsfsFileTest.assertFileContentsEqual( TEST_FILENAME + i, "A".getBytes() );

            }

            try
            {
                FileSystemImpl.getFileSystem().saveFile( TEST_FILENAME + FileSystemImpl.DEFAULT_RMS_NUMBER_RECORD_STORES + 1, dummyFile, true );

                fail( "testSaveManySmallFilesSingleRecordPerRecordStoreAllowed exception should have been thrown" );
            }
            catch( FileIOException fioe )
            {
                LOG.info( "Expected out of space exception thrown since exhausted number of record stores" );
            }
            catch( Exception e )
            {
                fail( e.toString() );
                LOG.info( e.toString() );
            }

        }
        catch( Exception e )
        {
            fail( e.getMessage() );
        }
    }

    public void test3()
    {
        LOG.info( "testSaveManySmallFilesSingleRecordPerRecordStoreAllowedCustomMaxRecordStores" );

        try
        {
            final int maxRecordStores = 20;

            FileSystemImpl fileSystemImpl = FileSystemImpl.getFileSystem();
            fileSystemImpl.setMaxRecordsPerRecordStore( 1 );
            fileSystemImpl.setMaxRecordStores( maxRecordStores );

            assertEquals( "iCurrentRecordStoreNumber 1", 1, fileSystemImpl.iCurrentRecordStoreNumber );
            //assertEquals( "iRecordsInCurrentRecordStore 0", 0, fileSystem.iRecordsInCurrentRecordStore );

            DummyFile dummyFile = new DummyFile( "A".getBytes(), "text" );

            for( int i = 1; i <= maxRecordStores; ++i )
            {
                FileSystemImpl.getFileSystem().saveFile( TEST_FILENAME + i, dummyFile, true );

                // We shouldn't need to move to a new record store for this few files of this size.
                assertEquals( "iCurrentRecordStoreNumber " + i, i, fileSystemImpl.iCurrentRecordStoreNumber );

                // We should be adding a new record each time.
                //assertEquals( "iRecordsInCurrentRecordStore 1", 1, fileSystem.iRecordsInCurrentRecordStore );

                RsfsFileTest.assertFileContentsEqual( TEST_FILENAME + i, "A".getBytes() );
            }

            try
            {
                FileSystemImpl.getFileSystem().saveFile( TEST_FILENAME + maxRecordStores + 1, dummyFile, true );

                fail( "testSaveManySmallFilesSingleRecordPerRecordStoreAllowed exception should have been thrown" );
            }
            catch( FileIOException fioe )
            {
                LOG.info( "Expected out of space exception thrown since exhausted number of record stores" );
            }
            catch( Exception e )
            {
                fail( e.toString() );
                LOG.info( e.toString() );
            }

        }
        catch( Exception e )
        {
            fail( e.getMessage() );
        }
    }

    public void test4()
    {
        LOG.info( "testSingleBigFileSingleRecordPerRecordStoreAllowedCustomMaxRecordStoresSmallMaximumRecordSize" );

        try
        {
            FileSystemImpl fileSystemImpl = FileSystemImpl.getFileSystem();
            fileSystemImpl.setMaxRecordsPerRecordStore( 1 );
            fileSystemImpl.setMaxRecordStores( 26 );
            fileSystemImpl.setMaxRecordSize( 1 );

            assertEquals( "iCurrentRecordStoreNumber 1", 1, fileSystemImpl.iCurrentRecordStoreNumber );
            //assertEquals( "iRecordsInCurrentRecordStore 0", 0, fileSystem.iRecordsInCurrentRecordStore );

            DummyFile dummyFile = new DummyFile( "ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes(), "text" );

            FileSystemImpl.getFileSystem().saveFile( TEST_FILENAME, dummyFile, true );

            // We shouldn't need to move to a new record store for this few files of this size.
            assertEquals( "iCurrentRecordStoreNumber 26", 26, fileSystemImpl.iCurrentRecordStoreNumber );

            // We should be adding a new record each time.
            //assertEquals( "iRecordsInCurrentRecordStore 1", 1, fileSystem.iRecordsInCurrentRecordStore );

            RsfsFileTest.assertFileContentsEqual( TEST_FILENAME, "ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes() );

            FileSystemImpl.getFileSystem().deleteFile( TEST_FILENAME );

            assertFalse( fileSystemImpl.exists( TEST_FILENAME ) );

        }
        catch( Exception e )
        {
            fail( e.getMessage() );
        }
    }

    public void test5()
    {
        LOG.info( "testSingleBigFileSingleRecordPerRecordStoreAllowedCustomMaxRecordStoresSmallMaximumRecordSizeExceeded" );

        try
        {
            FileSystemImpl fileSystemImpl = FileSystemImpl.getFileSystem();
            fileSystemImpl.setMaxRecordsPerRecordStore( 1 );
            fileSystemImpl.setMaxRecordStores( 26 );
            fileSystemImpl.setMaxRecordSize( 1 );

            assertEquals( "iCurrentRecordStoreNumber 1", 1, fileSystemImpl.iCurrentRecordStoreNumber );
            //assertEquals( "iRecordsInCurrentRecordStore 0", 0, fileSystem.iRecordsInCurrentRecordStore );

            // Alphabet plus 1 should be *just* too big.
            DummyFile dummyFile = new DummyFile( "ABCDEFGHIJKLMNOPQRSTUVWXYZ1".getBytes(), "text" );

            FileSystemImpl.getFileSystem().saveFile( TEST_FILENAME + "1", dummyFile, true );

            fail( "testSaveManySmallFilesSingleRecordPerRecordStoreAllowed exception should have been thrown" );
        }
        catch( FileIOException fioe )
        {
            LOG.info( "Expected out of space exception thrown since exhausted number of record stores" );
        }
        catch( Exception e )
        {
            fail( e.toString() );
            LOG.info( e.toString() );
        }

    }

    public void test6()
    {
        LOG.info( "testSingleBigFileSingleRecordPerRecordStoreAllowedCustomMaxRecordStoresSmallMaximumRecordSize2" );

        try
        {
            FileSystemImpl fileSystemImpl = FileSystemImpl.getFileSystem();
            fileSystemImpl.setMaxRecordsPerRecordStore( 2 );
            fileSystemImpl.setMaxRecordStores( 10 );
            fileSystemImpl.setMaxRecordSize( 2 );

            assertEquals( "iCurrentRecordStoreNumber 1", 1, fileSystemImpl.iCurrentRecordStoreNumber );
            //assertEquals( "iRecordsInCurrentRecordStore 0", 0, fileSystem.iRecordsInCurrentRecordStore );

            // 40 bytes.
            DummyFile dummyFile = new DummyFile( "ABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRST".getBytes(), "text" );

            FileSystemImpl.getFileSystem().saveFile( TEST_FILENAME, dummyFile, true );

            // We shouldn't need to move to a new record store for this few files of this size.
            assertEquals( "iCurrentRecordStoreNumber", 10, fileSystemImpl.iCurrentRecordStoreNumber );

            // We should be adding a new record each time.
            //assertEquals( "iRecordsInCurrentRecordStore", 2, fileSystem.iRecordsInCurrentRecordStore );

            RsfsFileTest.assertFileContentsEqual( TEST_FILENAME, "ABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRST".getBytes() );

            FileSystemImpl.getFileSystem().deleteFile( TEST_FILENAME );

            assertFalse( fileSystemImpl.exists( TEST_FILENAME ) );

        }
        catch( Exception e )
        {
            fail( e.getMessage() );
        }
    }

    public void test7()
    {
        LOG.info( "testSingleBigFileSingleRecordPerRecordStoreAllowedCustomMaxRecordStoresSmallMaximumRecordSize2" );

        try
        {
            FileSystemImpl fileSystemImpl = FileSystemImpl.getFileSystem();
            fileSystemImpl.setMaxRecordsPerRecordStore( 2 );
            fileSystemImpl.setMaxRecordStores( 10 );
            fileSystemImpl.setMaxRecordSize( 2 );

            assertEquals( "iCurrentRecordStoreNumber 1", 1, fileSystemImpl.iCurrentRecordStoreNumber );
            //assertEquals( "iRecordsInCurrentRecordStore 0", 0, fileSystem.iRecordsInCurrentRecordStore );

            // 40 bytes plus 1 should be *just* too big.
            DummyFile dummyFile = new DummyFile( "ABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRST1".getBytes(), "text" );

            FileSystemImpl.getFileSystem().saveFile( TEST_FILENAME + "1", dummyFile, true );

            fail( "testSaveManySmallFilesSingleRecordPerRecordStoreAllowed exception should have been thrown" );
        }
        catch( FileIOException fioe )
        {
            LOG.info( "Expected out of space exception thrown since exhausted number of record stores" );
        }
        catch( Exception e )
        {
            fail( e.toString() );
            LOG.info( e.toString() );
        }
    }

    protected int getNumberOfImplementedTestMethods()
    {
        return 7;
    }
}
